/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2008, 2009, 2010.

	This file is part of the Maxsi Library.

	Maxsi Library is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Library is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
	License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Library. If not, see <http://www.gnu.org/licenses/>.

	Maxsi Library
	A powerful Cross-Platform C++ General Purpose Library that allows you to
	efficiently create high-performance and reliable applications.

	MaxsiNetworking.h
	Blocking IO in a flexible manner.

******************************************************************************/

#ifndef MaxsiNetworking_H
#define MaxsiNetworking_H

BeginMaxsiNamespace

//=============================================================================
//	INetworking is an interface.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_ABSTRACT_BASECLASS

//=============================================================================
//	INetworking - An interface for dealing with network I/O.
//=============================================================================
MAXSI_CLASSLINK INetworking : public MaxsiInterface
{
	MAXSI_DECLARE_INTERFACE(INetworking);

public:
	virtual IBufferStreamer* Connect(MESTR* HostName, short Port, IBufferStreamer* Proxy = NULL) MAXSI_INTERFACE;
	virtual void CloseConnection(IBufferStreamer* Connection) MAXSI_INTERFACE;

};

//=============================================================================
//	INetworking - An interface for dealing with TCP network I/O.
//=============================================================================
MAXSI_CLASSLINK ITCP : public INetworking
{
	MAXSI_DECLARE_INTERFACE(ITCP);

};

#ifdef Maxsi_Support_POSIX
//=============================================================================
//	MaxsiTCPPOSIX is implemented.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	MaxsiTCPPOSIX - Deals with ITCP on POSIX.
//=============================================================================
MAXSI_CLASSLINK MaxsiTCPPOSIX : public ITCP
{
	MAXSI_DECLARE_IMPLEMENTATION(MaxsiTCPPOSIX, ITCP, MAXSI_INTERFACE_STATIC);

public:
	virtual IBufferStreamer* Connect(MESTR* HostName, short Port, IBufferStreamer* Proxy = NULL) MAXSI_INTERFACE;
	virtual void CloseConnection(IBufferStreamer* Connection) MAXSI_INTERFACE;

};

#endif

#ifdef Maxsi_Support_W32
//=============================================================================
//	MaxsiTCPW32 is implemented.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	MaxsiTCPW32 - Deals with ITCP on Windows.
//=============================================================================
MAXSI_CLASSLINK MaxsiTCPW32 : public ITCP
{
	MAXSI_DECLARE_IMPLEMENTATION(MaxsiTCPW32, ITCP, MAXSI_INTERFACE_STATIC);

public:
	virtual IBufferStreamer* Connect(MESTR* HostName, short Port, IBufferStreamer* Proxy = NULL) MAXSI_INTERFACE;
	virtual void CloseConnection(IBufferStreamer* Connection) MAXSI_INTERFACE;

};

#endif

//=============================================================================
//	ITCPStreamer is an interface.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_ABSTRACT_BASECLASS

//=============================================================================
//	ITCPStreamer - An interface for dealing with network I/O.
//=============================================================================
MAXSI_CLASSLINK ITCPStreamer : public IBufferStreamer
{
	MAXSI_DECLARE_INTERFACE(ITCPStreamer);

public:
	IBufferStreamer* Proxy;

public:
	virtual MaxsiError SetProxyInformation(IBufferStreamer* NewProxy, MESTR* HostName, short Port) MAXSI_INTERFACE;
	virtual void SetConnectionHandle(MaxsiHandle Handle) MAXSI_INTERFACE;
	virtual MaxsiHandle GetConnectionHandle() MAXSI_INTERFACE;

};

#ifdef Maxsi_Support_POSIX
//=============================================================================
//	MaxsiTCPStreamerPOSIX is implemented.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	MaxsiTCPStreamerPOSIX - Deals with ITCPStreamer on POSIX.
//=============================================================================
MAXSI_CLASSLINK MaxsiTCPStreamerPOSIX : public ITCPStreamer
{
	MAXSI_DECLARE_IMPLEMENTATION(MaxsiTCPStreamerPOSIX, ITCPStreamer, MAXSI_INTERFACE_DYNAMIC);

public:
	MaxsiTCPStreamerPOSIX();
	virtual ~MaxsiTCPStreamerPOSIX();

public:
	int Socket;

public:
	virtual MaxsiError SetProxyInformation(IBufferStreamer* Proxy, MESTR* HostName, short Port) MAXSI_INTERFACE;
	virtual void SetConnectionHandle(MaxsiHandle Handle) MAXSI_INTERFACE;
	virtual MaxsiHandle GetConnectionHandle() MAXSI_INTERFACE;

public:
	virtual int GetFlags() MAXSI_INTERFACE;
	virtual FileSize_t GetSize() MAXSI_INTERFACE;
	virtual MaxsiError SetSize(FileSize_t NewSize) MAXSI_INTERFACE;
	virtual FileSize_t GetPosition() MAXSI_INTERFACE;
	virtual MaxsiError Seek(FileSize_t Offset) MAXSI_INTERFACE;
	virtual MaxsiError Read(BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError ReadFrom(FileSize_t Offset, BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError Write(BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteTo(FileSize_t Offset, BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteFlush() MAXSI_INTERFACE;

};

#endif

#ifdef Maxsi_Support_W32
//=============================================================================
//	MaxsiTCPStreamerW32 is implemented.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY

//=============================================================================
//	MaxsiTCPStreamerW32 - Deals with ITCPStreamer on Windows.
//=============================================================================
MAXSI_CLASSLINK MaxsiTCPStreamerW32 : public ITCPStreamer
{
	MAXSI_DECLARE_IMPLEMENTATION(MaxsiTCPStreamerW32, ITCP, MAXSI_INTERFACE_DYNAMIC);

public:
	MaxsiTCPStreamerW32();
	virtual ~MaxsiTCPStreamerW32();

public:
	SOCKET Socket;

public:
	virtual MaxsiError SetProxyInformation(IBufferStreamer* Proxy, MESTR* HostName, short Port) MAXSI_INTERFACE;
	virtual void SetConnectionHandle(MaxsiHandle Handle) MAXSI_INTERFACE;
	virtual MaxsiHandle GetConnectionHandle() MAXSI_INTERFACE;

public:
	virtual int GetFlags() MAXSI_INTERFACE;
	virtual FileSize_t GetSize() MAXSI_INTERFACE;
	virtual MaxsiError SetSize(FileSize_t NewSize) MAXSI_INTERFACE;
	virtual FileSize_t GetPosition() MAXSI_INTERFACE;
	virtual MaxsiError Seek(FileSize_t Offset) MAXSI_INTERFACE;
	virtual MaxsiError Read(BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError ReadFrom(FileSize_t Offset, BYTE* Destination, size_t DestinationSize, size_t* ActualRead) MAXSI_INTERFACE;
	virtual MaxsiError Write(BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteTo(FileSize_t Offset, BYTE* Source, size_t SourceSize) MAXSI_INTERFACE;
	virtual MaxsiError WriteFlush() MAXSI_INTERFACE;

};

#endif	

MAXSI_LINK IBufferStreamer* CreateTCPConnection(MESTR* HostName, short Port);
MAXSI_LINK void CloseTCPConnection(IBufferStreamer* Connection);











// This has not been ported yet. It will be merged into Maxsi IO, first.
#if defined(Maxsi_Support_Linux)

MAXSI_STRUCTLINK MaxsiAsyncIOHandle
{
#ifdef Maxsi_Support_POSIX
	int	FD;
#endif
};

MAXSI_CLASSLINK MaxsiAsync
{
public:
	MaxsiAsync();
	virtual ~MaxsiAsync();

public:
	virtual MaxsiHandle AsyncListen(short Port) = 0;
	virtual MaxsiHandle AsyncConnect(MESTR* HostName, short Port) = 0;
	virtual MaxsiHandle AsyncOpenFile(MESTR* Path, FLAGS32 Mode) = 0;
	virtual MaxsiError SetUpAsyncIOHandleCallbacks(MaxsiHandle IOHandle) = 0;
	virtual MaxsiError MainLoop() = 0;
};

#ifdef Maxsi_Support_Epoll

MAXSI_TODO("Find a better value for this suggested value for how many concurrent FDs we are going to check. Note, however, this is not a limit, just a guess on how many FDs we need, the kernel performs better if we give it a realistic value.");
#define Maxsi_Epoll_DefaultSize 8

#define MAXSI_EPOLL_STATE_READ (1<<0)
#define MAXSI_EPOLL_STATE_WRITE (1<<1)

#define MAXSI_EPOLL_IS_SERVER (1<<2)
#define MAXSI_EPOLL_IS_SOCKET_LISTENER (1<<3)

#define MAXSI_EPOLL_BUF_SIZE 64

MAXSI_STRUCTLINK MaxsiAsyncEpollIOHandle : MaxsiAsyncIOHandle
{
	FLAGS32	State;
	timeval Begun;
	timeval	Last;
	timeval	Now;
	FileSize_t TotalRead;
	FileSize_t TotalWritten;
	bool PrintDebug;
	long NowMS;
	long LastMS;
	long BegunMS;
	float Elapsed;
	BYTE InBuf[MAXSI_EPOLL_BUF_SIZE];
	BYTE OutBuf[MAXSI_EPOLL_BUF_SIZE];

};


MAXSI_CLASSLINK MaxsiAsyncEpoll : public MaxsiAsync
{
public:
	MaxsiAsyncEpoll();
	~MaxsiAsyncEpoll();

public:
	int	EpollFD;

public:
	virtual MaxsiHandle AsyncListen(short Port);
	virtual MaxsiHandle AsyncConnect(MESTR* HostName, short Port);
	virtual MaxsiHandle AsyncOpenFile(MESTR* Path, FLAGS32 Mode);
	virtual MaxsiError SetUpAsyncIOHandleCallbacks(MaxsiHandle IOHandle);
	virtual MaxsiError MainLoop();
	virtual MaxsiError DoRead(MaxsiAsyncEpollIOHandle* Handle);
	virtual MaxsiError DoWrite(MaxsiAsyncEpollIOHandle* Handle);
	virtual MaxsiError AcceptClient(MaxsiAsyncEpollIOHandle* Handle);

};
#endif

MAXSI_LINK MaxsiAsync* Async();

#endif

EndMaxsiNamespace

#endif
